{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ipyvuetify\n",
    " * QuantStack/SocGen (Olivier Borderier) project\n",
    " * Made by Mario Buikhuizen\n",
    " * Wraps Vuetify\n",
    "     * Vue based\n",
    "     * Material Design\n",
    " * Rich set of composable widgets following Material Design spec."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ipyvuetify as v\n",
    "import ipywidgets as widgets\n",
    "from threading import Timer\n",
    "lorum_ipsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v.Layout(children=[\n",
    "    v.Btn(color='primary', children=['primary']),\n",
    "    v.Btn(color='error', children=['error']),\n",
    "    v.Btn(color='pink lighten-4', children=['custom']),\n",
    "    v.Btn(color='#654321', dark=True, children=['hex']),\n",
    "    v.Btn(color='#654321', disabled=True, children=['disabled']),\n",
    "\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v.Layout(children=[\n",
    "    v.Btn(color='primary', flat=True, children=['flat']),\n",
    "    v.Btn(color='primary', flat=True, disabled=True, children=['flat']),\n",
    "    v.Btn(color='primary', round=True, children=['round']),\n",
    "    v.Btn(color='primary', round=True, disabled=True, children=['round']),\n",
    "    v.Btn(color='primary', depressed=True, children=['depressed']),\n",
    "    v.Btn(color='primary', flat=True, icon=True, children=[v.Icon(children=['thumb_up'])]),\n",
    "    v.Btn(color='primary', outline=True, children=['outline']),\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v.Layout(children=[\n",
    "    v.Btn(color='primary', small=True, children=['small']),\n",
    "    v.Btn(color='primary', children=['normal']),\n",
    "    v.Btn(color='primary', large=True, children=['large']),\n",
    "    v.Btn(color='primary', small=True, fab=True, children=[v.Icon(children=['edit'])]),\n",
    "    v.Btn(color='primary', fab=True, children=[v.Icon(children=['edit'])]),\n",
    "    v.Btn(color='primary', fab=True, large=True, children=[v.Icon(children=['edit'])]),\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def toggleLoading():\n",
    "    button2.loading = not button2.loading\n",
    "    button2.disabled = button2.loading\n",
    "\n",
    "def on_loader_click(*args):\n",
    "    toggleLoading()\n",
    "    Timer(2.0, toggleLoading).start()\n",
    "    \n",
    "button2 = v.Btn(loading=False, children=['loader'])\n",
    "button2.on_event('click', on_loader_click)\n",
    "\n",
    "v.Layout(children=[button2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "toggle_single = v.BtnToggle(v_model=2, class_='mr-3', children=[\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_align_left'])]),\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_align_center'])]),\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_align_right'])]),\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_align_justify'])]),\n",
    "])\n",
    "\n",
    "toggle_multi = v.BtnToggle(v_model=[0,2], multiple=True, children=[\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_bold'])]),\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_italic'])]),\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_underline'])]),\n",
    "    v.Btn(flat=True, children=[v.Icon(children=['format_color_fill'])]),\n",
    "])\n",
    "\n",
    "v.Layout(children=[\n",
    "    toggle_single,\n",
    "    toggle_multi,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v.Layout(children=[\n",
    "    v.Btn(color='primary', children=[\n",
    "        v.Icon(left=True, children=['fingerprint']),\n",
    "        'Icon left'\n",
    "    ]),\n",
    "    v.Btn(color='primary', children=[\n",
    "        'Icon right',\n",
    "        v.Icon(right=True, children=['fingerprint']),\n",
    "    ]),\n",
    "    v.Tooltip(bottom=True, children=[\n",
    "        v.Btn(slot='activator', color='primary', children=[\n",
    "           'tooltip' \n",
    "        ]),\n",
    "        'Insert tooltip text here'\n",
    "    ])    \n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def on_menu_click(widget, event, data):\n",
    "    if len(layout.children) == 1:\n",
    "        layout.children = layout.children + [info]\n",
    "    info.children=[f'Item {items.index(widget)+1} clicked']\n",
    "    \n",
    "\n",
    "items = [v.ListTile(children=[\n",
    "    v.ListTileTitle(children=[\n",
    "        f'Click me {i}'])]) \n",
    "         for i in range(1, 5)]\n",
    "\n",
    "for item in items:\n",
    "    item.on_event('click', on_menu_click)\n",
    "\n",
    "menu = v.Menu(offset_y=True, children=[\n",
    "    v.Btn(slot='activator', color='primary', children=[\n",
    "        'menu', \n",
    "        v.Icon(right=True, children=[\n",
    "            'arrow_drop_down'\n",
    "        ])\n",
    "    ]),\n",
    "    v.List(children=items)\n",
    "])\n",
    "\n",
    "info = v.Chip()\n",
    "\n",
    "layout = v.Layout(children=[\n",
    "    menu\n",
    "])\n",
    "layout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "v.Dialog(v_model=False, width='500', children=[\n",
    "        v.Btn(slot=\"activator\", color='success', dark=True, children=[\n",
    "            \"Open dialog\"\n",
    "        ]),\n",
    "        v.Card(children=[\n",
    "            v.CardTitle(class_='headline gray lighten-2', primary_title=True, children=[\n",
    "                \"Lorem ipsum\"]),\n",
    "            v.CardText(children=[\n",
    "                lorum_ipsum])\n",
    "        ])\n",
    "    ])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "slider = v.Slider(v_model=25)\n",
    "slider2 = v.Slider(thumb_label=True, v_model=25)\n",
    "slider3 = v.Slider(thumb_label='always', v_model=25)\n",
    "\n",
    "widgets.jslink((slider, 'v_model'), (slider2, 'v_model'))\n",
    "widgets.jslink((slider, 'v_model'), (slider3, 'v_model'))\n",
    "\n",
    "v.Container(children=[\n",
    "    slider,\n",
    "    slider2,\n",
    "    slider3\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "select1=v.Select(label=\"Choose option\", items=['Option a', 'Option b', 'Option c'])\n",
    "v.Layout(children=[select1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tab_list = [v.Tab(children=[f'Tab {i}']) for i in range(1,4)]\n",
    "content_list = [v.TabItem(children=[lorum_ipsum]) for i in range(1,4)] \n",
    "tabs = v.Tabs(\n",
    "    v_model=1, \n",
    "    children=tab_list + content_list)\n",
    "tabs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def on_click(widget, event, data):\n",
    "   vnd.v_model = not vnd.v_model\n",
    "\n",
    "drawer_button = v.Btn(color='primary', children=['Close drawer'])\n",
    "drawer_button.on_event('click', on_click)\n",
    "\n",
    "vnd = v.NavigationDrawer(v_model=False, absolute=True, right=True, children=[\n",
    "    drawer_button\n",
    "])\n",
    "\n",
    "show_drawer = v.Btn(color='primary', children=['Toggle drawer'])\n",
    "show_drawer.on_event('click', on_click)\n",
    "\n",
    "v.Layout(children=[vnd, show_drawer]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "vepc1 = v.ExpansionPanelContent(children=[\n",
    "    v.Html(tag='div', slot='header', children=['item1']),\n",
    "    v.Card(children=[\n",
    "        v.CardText(children=['First Text'])])])\n",
    "\n",
    "vepc2 = v.ExpansionPanelContent(children=[\n",
    "    v.Html(tag='div', slot='header', children=['item2']),\n",
    "    v.Card(children=[\n",
    "        v.CardText(children=['Second Text'])])])\n",
    "\n",
    "vep = v.ExpansionPanel(children=[vepc1, vepc2])\n",
    "vl = v.Layout(children=[vep])\n",
    "vl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ipyvuetify as v\n",
    "\n",
    "from traitlets import (Unicode, List, Bool, Any)\n",
    "\n",
    "class MyApp(v.VuetifyTemplate):\n",
    "    dark = Bool(True).tag(sync=True)\n",
    "    drawers = Any(['Default (no property)', 'Permanent', 'Temporary']).tag(sync=True)\n",
    "    model = Any(None).tag(sync=True)\n",
    "    type = Unicode('default (no property)').tag(sync=True)\n",
    "    clipped = Bool(False).tag(sync=True)\n",
    "    floating = Bool(True).tag(sync=True)\n",
    "    mini = Bool(False).tag(sync=True)\n",
    "    inset = Bool(False).tag(sync=True)\n",
    "    \n",
    "    template = Unicode('''\n",
    "        <template>\n",
    "  <v-app id=\"sandbox\" :dark=\"dark\">\n",
    "    <v-navigation-drawer\n",
    "      v-model=\"model\"\n",
    "      :permanent=\"type === 'permanent'\"\n",
    "      :temporary=\"type === 'temporary'\"\n",
    "      :clipped=\"clipped\"\n",
    "      :floating=\"floating\"\n",
    "      :mini-variant=\"mini\"\n",
    "      absolute\n",
    "      overflow\n",
    "      app\n",
    "    >\n",
    "    </v-navigation-drawer>\n",
    "    <v-toolbar :clipped-left=\"clipped\" app absolute>\n",
    "      <v-toolbar-side-icon\n",
    "        v-if=\"type !== 'permanent'\"\n",
    "        @click.stop=\"model = !model\"\n",
    "      ></v-toolbar-side-icon>\n",
    "      <v-toolbar-title>Vuetify</v-toolbar-title>\n",
    "    </v-toolbar>\n",
    "    <v-content>\n",
    "      <v-container fluid>\n",
    "        <v-layout align-center justify-center>\n",
    "          <v-flex xs10>\n",
    "            <v-card>\n",
    "              <v-card-text>\n",
    "                <v-layout row wrap>\n",
    "                  <v-flex xs12 md6>\n",
    "                    <span>Scheme</span>\n",
    "                    <v-switch v-model=\"dark\" primary label=\"Dark\"></v-switch>\n",
    "                  </v-flex>\n",
    "                  <v-flex xs12 md6>\n",
    "                    <span>Drawer</span>\n",
    "                    <v-radio-group v-model=\"type\" column>\n",
    "                      <v-radio\n",
    "                        v-for=\"drawer in drawers\"\n",
    "                        :key=\"drawer\"\n",
    "                        :label=\"drawer\"\n",
    "                        :value=\"drawer.toLowerCase()\"\n",
    "                        primary\n",
    "                      ></v-radio>\n",
    "                    </v-radio-group>\n",
    "                    <v-switch v-model=\"clipped\" label=\"Clipped\" primary></v-switch>\n",
    "                    <v-switch v-model=\"floating\" label=\"Floating\" primary></v-switch>\n",
    "                    <v-switch v-model=\"mini\" label=\"Mini\" primary></v-switch>\n",
    "                  </v-flex>\n",
    "                  <v-flex xs12 md6>\n",
    "                    <span>Footer</span>\n",
    "                    <v-switch v-model=\"inset\" label=\"Inset\" primary></v-switch>\n",
    "                  </v-flex>\n",
    "                </v-layout>\n",
    "              </v-card-text>\n",
    "              <v-card-actions>\n",
    "                <v-spacer></v-spacer>\n",
    "                <v-btn flat>Cancel</v-btn>\n",
    "                <v-btn flat color=\"primary\">Submit</v-btn>\n",
    "              </v-card-actions>\n",
    "            </v-card>\n",
    "          </v-flex>\n",
    "        </v-layout>\n",
    "      </v-container>\n",
    "    </v-content>\n",
    "    <v-footer :inset=\"inset\" app>\n",
    "      <span class=\"px-3\">&copy; {{ new Date().getFullYear() }}</span>\n",
    "    </v-footer>\n",
    "  </v-app>\n",
    "</template>''').tag(sync=True)\n",
    "   \n",
    "    \n",
    "app = MyApp()\n",
    "app"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "app.inset = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "app.dark = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "app.type = 'permanent'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercise\n",
    "Mapping of vuetify components and ipyvuetify widgets [are explained in the docs](https://github.com/mariobuikhuizen/ipyvuetify#usage). Use the [vuetify documentation](https://vuetifyjs.com/en/components/api-explorer) to find how to make a RadioGroup, with RadioButtons.\n",
    "We provide the ipywidget solution, it is up to you to create the ipyvuetify solution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = ['pepperoni', 'pineapple', 'anchovies']\n",
    "widgets.RadioButtons(options=options, value=options[0], description='Pizza topping:')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# %load solutions/ipyvuetify/radio_group.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making a new widget\n",
    "Using the VuetifyTemplate, we can make a new widget on the fly. Let us make a RadioGroup widget that behaves more like core ipwidgets. Resources that are helpful for this are:\n",
    " * https://vuejs.org/v2/guide/list.html\n",
    " * https://vuetifyjs.com/en/components/selection-controls\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ipyvuetify as v\n",
    "import traitlets\n",
    "\n",
    "class MyRadioGroup(v.VuetifyTemplate):\n",
    "    description = traitlets.Unicode('give me a description').tag(sync=True)\n",
    "    labels = traitlets.List(traitlets.Unicode(), default_value=['Radio 1', 'Radio 2']).tag(sync=True)\n",
    "    value = traitlets.Int(0, help=\"index of selected value\").tag(sync=True)\n",
    "    template = traitlets.Unicode('''\n",
    "    <v-radio-group :label=\"description\" v-model=\"value\">\n",
    "        <v-radio v-for=\"(radiolabel, index) in labels\"\n",
    "                 :label=\"radiolabel\"\n",
    "                 :value=\"index\"\n",
    "                 :key=\"index\"\n",
    "        ></v-radio>\n",
    "    </v-radio-group>\n",
    "    ''').tag(sync=True)\n",
    "\n",
    "rg2 = MyRadioGroup()\n",
    "rg2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rg2.labels = options\n",
    "rg2.description = \"Pizza toppings\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rg2.value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rg2.value = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "slider = widgets.IntSlider(min=0, max=2, value=2)\n",
    "widgets.jslink((slider, 'value'), (rg2, 'value'))\n",
    "slider"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "widgets-tutorial",
   "language": "python",
   "name": "widgets-tutorial"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
